package com.rest.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.api.model.ApiParameter;
import com.api.model.ApiService;
import com.api.model.ApiServiceMethod;
import com.api.rest.model.RestClass;
import com.api.rest.model.RestMethod;
import com.rest.ApiRestService;
import com.rest.ApiServices;
import com.rest.ServicesService;

public class ServicesServiceImpl implements ServicesService {

	private final List<ApiServices> apiServices = new ArrayList<ApiServices>();

	private final Map<String, Map<String, ApiRestService>> services = new HashMap<String, Map<String, ApiRestService>>();

	private final String apiVersion;

	public ServicesServiceImpl(ApiRestHandler apiRestHandler) {
		if (apiRestHandler == null) {
			throw new IllegalArgumentException("ApiRestHandler cannot be null");
		}

		this.apiVersion = apiRestHandler.getApiVersion();

		List<Class<?>> apis = apiRestHandler.getApis();

		for (Class<?> apiClass : apis) {
			String apiName = apiClass.getSimpleName();

			RestClass restClass = apiRestHandler.getRestClass(apiClass);
			List<RestMethod> methods = restClass.getMethods();

			ApiService apiService = apiRestHandler.getApiService(apiClass);
			List<ApiServiceMethod> apiMethods = apiService.getMethods();

			List<String> services = new ArrayList<String>();
			Map<String, ApiRestService> apiServices = new HashMap<String, ApiRestService>();
			for (int i = 0; i < methods.size(); i++) {
				String serviceName = methods.get(i).getName();
				List<ApiParameter> parameters = apiMethods.get(i).getParameters();
				String params = getParameters(parameters);
				serviceName += params;

				ApiRestService restService = new ApiRestService(methods.get(i), apiMethods.get(i));

				services.add(serviceName);
				apiServices.put(serviceName, restService);
			}

			this.apiServices.add(new ApiServices(apiName, services));
			this.services.put(apiName, apiServices);
		}

		Collections.sort(this.apiServices);
	}

	@Override
	public List<ApiServices> getServices() {
		return apiServices;
	}

	private String getParameters(List<ApiParameter> parameters) {
		String result = "(";
		for (ApiParameter parameter : parameters) {
			if (parameter.isNotNull()) {
				result += "*";
			}
			result += parameter.getName();
			result += ", ";
		}
		if (parameters.size() > 0) {
			result = result.substring(0, result.length() - 2);
		}

		result += ")";
		return result;
	}

	@Override
	public ApiRestService getService(String api, String request) {

		Map<String, ApiRestService> map = null;

		if (!this.services.containsKey(api)) {
			throw new IllegalStateException("Api doesn't exists");
		}
		map = this.services.get(api);
		if (!map.containsKey(request)) {
			throw new IllegalStateException(String.format("Api '%s' doesn't have a service '%s'", api, request));
		}
		return map.get(request);
	}

	@Override
	public String getVersion() {
		return "\"" + apiVersion + "\"";
	}
}
